﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation.BusinessRules;
using Sinacor.Infra.Service.Security.Authorization;

namespace Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessLogic
{
    public class ManutencaoOrdens : BaseBusinessLogic
    {
        #region Campos

        private int ERRO_RESULTADO = 109448;
        private int ERRO_PARAMETRONAOINFORMADO = 109381;
        private int NUM_ORDEM_NAOINFORMADO = 109334;
        private int DT_ORDEM_NAOINFORMADO = 109335;
        private int NUM_ORDEM_SUB_NAOINFORMADO = 109336;
        private int ERRO_REQUEST_NAOINFORMADO = 109338;
        private int ERRO_ACESSO_MORD = 109337;
        private int CLIENTE_NAO_INFORMADO = 109421;
        private int MERCADO_NAO_INFORMADO = 109422;
        private int ATIVO_NAO_INFORMADO = 109423;
        private int QUANTIDADE_NAO_INFORMADA = 109424;
        private int ERRO_INDICE_UM_NEGATIVO = 109425;
        private int ERRO_MOVIMENTO_FECHADO = 109501;
        private int ERRO_ACESSO_INCLUSAO_ORDEM = 109384;
        private int ERRO_ORDEM_MAE_NAO_ENCONTRADA = 109427;
        private int OBJETO_ORDEM_NULO = 109426;
        private int USUARIO_SEM_PERMISSAO_PARA_CANCELAR_ORDENS = 109461;
        private int NUMERO_SUBSEQUENCIA_IGUAL_ZERO = 109286;
        private int DETALHE_ORDEM_NAO_EXISTE = 109465;
        private int ERRO_EM_DESCASAR = 109292;
        private int ERRO_CASAR_DETALHES = 109450;
        private int ERRO_INESPERADO_ALTERACAO_ALOCACAO = 109447;
        private int ERRO_INESPERADO_ALTERACAO_SITUACAO_ORDEM = 109449;

        #endregion

        #region Construtor
        public ManutencaoOrdens() { }
        #endregion

        #region Metodos
        /// <summary>
        /// Consultar Detalhes da Ordem
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<BusinessEntity.DetalheOrdem> ConsultarDetalhesOrdem(BusinessEntity.ChaveOrdem request)
        {
            if (request == null)
                throw new BusinessException(ERRO_PARAMETRONAOINFORMADO);

            if (request.NumeroOrdem == Int32.MinValue)
                throw new BusinessException(NUM_ORDEM_NAOINFORMADO);

            if (request.DataOrdem == DateTime.MinValue)
                throw new BusinessException(DT_ORDEM_NAOINFORMADO);

            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            return manutencao.ConsultarDetalhesOrdem(request);
        }

        /// <summary>
        /// Consultar Ordens
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<BusinessEntity.Ordem> ConsultarOrdens(BusinessEntity.Parameter.FiltroOrdem request)
        {
            if (request == null)
                throw new BusinessException(ERRO_REQUEST_NAOINFORMADO);

            if (!Sinacor.Infra.Service.Security.Authorization.AuthorizationContext.Current.CheckUserAccess("MORD", "ORD"))
                throw new BusinessException(ERRO_ACESSO_MORD);

            if (request.ApenasSemCliente)
            {
                request.Cliente = null;
                request.ApelidoCliente = string.Empty;
            }

            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            return AtribuirSituacaoCasamentoOrdem(manutencao.ConsultarOrdens(request));


        }

        /// <summary>
        /// Atribui a situação do casamento da ordem
        /// </summary>
        /// <param name="ordens"></param>
        private List<BusinessEntity.Ordem> AtribuirSituacaoCasamentoOrdem(List<BusinessEntity.Ordem> ordens)
        {
            foreach(BusinessEntity.Ordem item in ordens)
            {
                if(item.QuantidadeExecutada == item.Quantidade)
                {
                    item.SituacaoCasamento = BusinessEntity.Enum.SituacaoCasamento.Casada;
                }
                else if(item.QuantidadeExecutada > 0 && item.QuantidadeExecutada < item.Quantidade)
                {
                    item.SituacaoCasamento = BusinessEntity.Enum.SituacaoCasamento.ParcialmenteCasada;
                }
                else if(item.QuantidadeExecutada == 0)
                    item.SituacaoCasamento = BusinessEntity.Enum.SituacaoCasamento.NaoCasada;
            }

            return ordens;
        }

        /// <summary>
        /// Verificar Existencia da Ordem
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool VerificarExistenciaOrdem(BusinessEntity.ChaveOrdem request)
        {
            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            return manutencao.VerificarExistenciaOrdem(request);
        }

        /// <summary>
        /// Obter dados da Ordem
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Ordem ObterOrdem(BusinessEntity.ChaveOrdem request)
        {
            if (request == null)
                throw new BusinessException(ERRO_PARAMETRONAOINFORMADO);

            if (request.NumeroOrdem == 0)
                throw new BusinessException(NUM_ORDEM_NAOINFORMADO);

            if (request.DataOrdem == DateTime.MinValue)
                throw new BusinessException(DT_ORDEM_NAOINFORMADO);

            if (request.NumeroOrdemSubSequencia == Int32.MinValue)
                throw new BusinessException(NUM_ORDEM_SUB_NAOINFORMADO);


            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            return manutencao.ObterOrdem(request);
        }

        /// <summary>
        /// Método CalcularFinanceiro
        /// </summary>
        public void CalcularFinanceiro()
        {
            //1) Chamar o método Movimento.ControleMovimentoOrdens.ObterInformacoesMovimento(), passar como parâmetro de entrada uma instância do objeto DataMovimento (new DataMovimento())
            Movimento.BusinessLogic.ControleMovimentoOrdens movimento = new Sinacor.Servico.Bovespa.Movimento.BusinessLogic.ControleMovimentoOrdens();
            Movimento.BusinessEntity.InformacoesMovimento respostaMovi = new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.InformacoesMovimento();

            respostaMovi = movimento.ObterInformacoesMovimento(new Movimento.BusinessEntity.DataMovimento());


            //2) Chamar o método ResourceAccess.ManutencaoOrdens.CalcularFinanceiro(), passando como parâmetro de entrada a propriedade DataMovimento, obtida no passo 1.
            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();
            BusinessEntity.Resultado resultado = new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Resultado();

            resultado = manutencao.CalcularFinanceiro(respostaMovi.DataMovimento);



            if (resultado.Sucesso == false)
            {
                if (resultado.CodigoErro == -1)
                {
                    throw new BusinessException(ERRO_RESULTADO);
                }
                else
                {
                    this.TratarExcecoes(resultado);
                }
            }
        }


        /// <summary>
        /// Realiza o tratamento de exceções geradas em chamadas de função ou procedure
        /// </summary>
        /// <param name="resultado"></param>
        private void TratarExcecoes(BusinessEntity.Resultado resultado)
        {
            if (string.IsNullOrEmpty(resultado.Argumentos))
                throw new BusinessException(resultado.CodigoErro);
            else
            {
                List<Object> _params = ErrorMessage.ConvertXmlArgumentsToParameters(resultado.Argumentos);

                if (_params != null)
                    throw new BusinessException(resultado.CodigoErro, _params.ToArray());
                else
                    throw new BusinessException(resultado.CodigoErro);
            }

        }

        /// <summary>
        /// ObterSaldoNegociavel
        /// </summary>
        /// <param name="request">DadosSaldoNegociavel</param>
        /// <returns>Saldo</returns>
        public BusinessEntity.Saldo ObterSaldoNegociavel(BusinessEntity.DadosSaldoNegociavel request)
        {
            if (request == null)
                throw new BusinessException(ERRO_PARAMETRONAOINFORMADO);

            if (request.Cliente == 0)
                throw new BusinessException(CLIENTE_NAO_INFORMADO);

            if (request.Mercado == null)
                throw new BusinessException(MERCADO_NAO_INFORMADO);

            if (string.IsNullOrEmpty(request.Ativo))
                throw new BusinessException(ATIVO_NAO_INFORMADO);

            if (request.Quantidade == 0)
                throw new BusinessException(QUANTIDADE_NAO_INFORMADA);

            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            BusinessEntity.Resultado result = manutencao.ObterSaldoNegociavel(request);

            if (!result.Sucesso)
            {
                if (result.CodigoErro == -1)
                {
                    throw new BusinessException(ERRO_INDICE_UM_NEGATIVO);
                }
                else
                {
                    this.TratarExcecoes(result);
                }
            }

            BusinessEntity.Saldo saldo = new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Saldo() { Valor = Convert.ToDecimal(result.Valor) };

            return saldo;
        }

        /// <summary>
        /// FecharOrdemAdministradaConcorrente
        /// </summary>
        /// <param name="request"></param>
        public void FecharOrdemAdministradaConcorrente(Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.ChaveOrdem request)
        {
            Movimento.BusinessEntity.InformacoesMovimento mov = new Movimento.BusinessLogic.ControleMovimentoOrdens().ObterInformacoesMovimento
                (
                    new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento()
                );

            if (mov.EstadoMovimento != Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            if (request == null)
                throw new BusinessException(ERRO_PARAMETRONAOINFORMADO);

            if (request.NumeroOrdem == Int32.MinValue)
                throw new BusinessException(NUM_ORDEM_NAOINFORMADO);

            if (request.DataOrdem == DateTime.MinValue)
                throw new BusinessException(DT_ORDEM_NAOINFORMADO);

            if (request.NumeroOrdemSubSequencia == Int32.MinValue)
                throw new BusinessException(NUM_ORDEM_SUB_NAOINFORMADO);

            ResourceAccess.ManutencaoOrdens manutencao = new ResourceAccess.ManutencaoOrdens();

            manutencao.FecharOrdemAdministradaConcorrente(request);

        }

        /// <summary>
        /// IncluirOrdem
        /// </summary>
        /// <param name="ordem">BusinessEntity.Ordem</param>
        /// <returns>BusinessEntity.ChaveOrdem</returns>
        public BusinessEntity.ChaveOrdem IncluirOrdem(Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Ordem ordem)
        {
            //Usuário possui permissão para incluir ordem?
            if (!AuthorizationContext.Current.CheckUserAccess("IORD", "ORD"))
            {
                throw new BusinessException(ERRO_ACESSO_INCLUSAO_ORDEM);
            }

            Movimento.BusinessEntity.InformacoesMovimento mov = null;
            Movimento.BusinessLogic.ControleMovimentoOrdens blMov = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento param = new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento();

            mov = blMov.ObterInformacoesMovimento(param);

            if (mov.EstadoMovimento != Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            BusinessRulesValidation.ValidadorInclusaoOrdem validacaoInclusao = new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessLogic.BusinessRulesValidation.ValidadorInclusaoOrdem();
            validacaoInclusao.EntityToValidate = ordem;

            BusinessRulesValidator validador = new BusinessRulesValidator();
            validador.AddValidation("ValidadorInclusaoOrdem", validacaoInclusao);

            validador.Validate();

            ordem = validacaoInclusao.EntityToValidate;

            ordem.NumeroOrdem = this.GerarNumeroOrdem();

            ResourceAccess.ManutencaoOrdens manut = new ResourceAccess.ManutencaoOrdens();

            manut.IncluirOrdem(ordem);

            manut.IncluirObservacao(ordem);

            return new BusinessEntity.ChaveOrdem()
            {
                NumeroOrdem = ordem.NumeroOrdem,
                DataOrdem = ordem.DataOrdem,
                NumeroOrdemSubSequencia = ordem.NumeroOrdemSubSequencia
            };
        }

        private int GerarNumeroOrdem()
        {
            return new ResourceAccess.ManutencaoOrdens().GerarNumeroOrdem();
        }


        public Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Resultado GerarCodigoCasamento(Bovespa.ManutencaoOrdens.BusinessEntity.Ordem request)
        {
            return new ResourceAccess.ManutencaoOrdens().GerarCodigoCasamento(request);
        }


        /// <summary>
        /// IncluirDetalheOrdem
        /// </summary>
        /// <param name="request">BusinessEntity.DetalheOrdem</param>
        /// <returns>BusinessEntity.ChaveOrdem</returns>
        public BusinessEntity.ChaveOrdem IncluirDetalheOrdem(BusinessEntity.DetalheOrdem request)
        {
            //Usuário possui permissão para incluir ordem?
            if (!AuthorizationContext.Current.CheckUserAccess("IORD", "ORD"))
                throw new BusinessException(ERRO_ACESSO_INCLUSAO_ORDEM);

            //ValidarEstadoMovimento
            Movimento.BusinessEntity.InformacoesMovimento mov = new Movimento.BusinessLogic.ControleMovimentoOrdens().ObterInformacoesMovimento
                (
                    new Movimento.BusinessEntity.DataMovimento()
                );

            if (mov.EstadoMovimento != Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            //Obtém dados da ordem mãe
            BusinessEntity.ChaveOrdem chaveOrdem = new BusinessEntity.ChaveOrdem();
            chaveOrdem.NumeroOrdem = request.NumeroOrdem;
            chaveOrdem.NumeroOrdemSubSequencia = 0;
            chaveOrdem.DataOrdem = request.DataOrdem;

            BusinessEntity.Ordem ordem = this.ObterOrdem(chaveOrdem);

            if (ordem == null)
                throw new BusinessException(ERRO_ORDEM_MAE_NAO_ENCONTRADA);

            //Processamento responsável pela validação de inclusão de um detalhe da ordem
            BusinessRulesValidation.ValidadorInclusaoDetalheOrdem validacaoInclusaoDetalheOrdem = new BusinessRulesValidation.ValidadorInclusaoDetalheOrdem(ordem);
            validacaoInclusaoDetalheOrdem.EntityToValidate = request;

            BusinessRulesValidator validador = new BusinessRulesValidator();
            validador.AddValidation("ValidadorInclusaoDetalheOrdem", validacaoInclusaoDetalheOrdem);

            validador.Validate();

            //Criar uma ordem herdando informações da ordem mãe e do detalhe da ordem
            ordem = this.CriarOrdemDetalhe(validacaoInclusaoDetalheOrdem.OrdemMae, request);

            //Gerar número de subsequência para o detalhe
            ordem.NumeroOrdemSubSequencia = new ResourceAccess.ManutencaoOrdens().GerarNumeroSubSequenciaOrdem(chaveOrdem);

            //Incluir detalhe da ordem
            new ResourceAccess.ManutencaoOrdens().IncluirOrdem(ordem);

            //Retornar chave do detalhe da ordem
            chaveOrdem.DataOrdem = ordem.DataOrdem;
            chaveOrdem.NumeroOrdem = ordem.NumeroOrdem;
            chaveOrdem.NumeroOrdemSubSequencia = ordem.NumeroOrdemSubSequencia;

            return chaveOrdem;
        }

        /// <summary>
        /// CriarOrdemDetalhe
        /// </summary>
        /// <param name="ordemMae">BusinessEntity.Ordem</param>
        /// <param name="detalhe">BusinessEntity.DetalheOrdem</param>
        /// <returns>BusinessEntity.Ordem</returns>
        private BusinessEntity.Ordem CriarOrdemDetalhe(BusinessEntity.Ordem ordemMae, BusinessEntity.DetalheOrdem detalhe)
        {
            ordemMae.Ativo = detalhe.Ativo;
            ordemMae.Mercado = (Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Enum.TipoMercado)detalhe.Mercado;
            ordemMae.PrazoVencimentoTermo = detalhe.PrazoVencimentoTermo;
            ordemMae.Quantidade = detalhe.Quantidade;
            ordemMae.Preco = detalhe.Preco;
            ordemMae.NaturezaOperacao = detalhe.NaturezaOperacao;
            ordemMae.Carteira = detalhe.Carteira;
            ordemMae.Distribuida = false;
            ordemMae.QuantidadeExecutada = 0;
            ordemMae.ValorFinanciamento = null;
            ordemMae.PercentualFinanciamento = null;
            ordemMae.NomeCliente = null;
            ordemMae.IndicadorGravaLog = false;
            ordemMae.QuantidadeAnexoIV = 0;
            ordemMae.QuantidadeAnexoV = 0;
            ordemMae.ApelidoCliente = null;
            ordemMae.CodigoUsuario = AuthorizationContext.Current.UserId;
            ordemMae.QuantidadeCanceladaOferta = 0;
            ordemMae.NumeroOrdemOriginal = 0;
            ordemMae.TimeStampInterna = new Calendario.BusinessLogic.Calendario().ObterTimeStamp();

            return ordemMae;
        }

        /// <summary>
        /// Cancela ordem
        /// </summary>
        /// <param name="request"></param>
        /// <param name="justificativa"></param>
        public void CancelarOrdem(BusinessEntity.ChaveOrdem request, BusinessEntity.Justificativa justificativa)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = null;
            Movimento.BusinessEntity.InformacoesMovimento infoMovimento = null;
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
            BusinessLogic.Justificativa blJustificativa = new BusinessLogic.Justificativa();
            BusinessEntity.Ordem ordem = null;
            BusinessEntity.ChaveOrdem chave = null;

            //Verificar se usuário possui permissão para cancelar ordens
            if (!AuthorizationContext.Current.CheckUserAccess("EORD", "ORD"))
                throw new BusinessException(ERRO_ACESSO_INCLUSAO_ORDEM);

            blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            infoMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());

            //Valida estado do movimento
            if (infoMovimento.EstadoMovimento != Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            ordem = this.ObterOrdem(request);

            if (ordem == null)
                throw new BusinessException(OBJETO_ORDEM_NULO);

            if (ordem.TipoOrdem == BusinessEntity.Enum.TipoOrdem.Financiamento || ordem.CodigoISIN.Substring(6, 2).ToUpper() == "PP")
            {
                ordem.Detalhes = this.ConsultarDetalhesOrdem(request);
            }


            //Validar se a ordem pode ser casada
            BusinessRulesValidation.ValidadorCancelamentoOrdem validacaoCancelamentoOrdem = new BusinessRulesValidation.ValidadorCancelamentoOrdem(justificativa, infoMovimento);
            validacaoCancelamentoOrdem.EntityToValidate = ordem;

            BusinessRulesValidator validador = new BusinessRulesValidator();
            validador.AddValidation("ValidadorCancelamentoOrdem", validacaoCancelamentoOrdem);
            validador.Validate();

            //Verifica se retornou algum erro na validação
            if (!validador.HasErrors)
            {
                if (ordem.Detalhes != null && ordem.Detalhes.Count > 0)
                {
                    foreach (BusinessEntity.DetalheOrdem item in ordem.Detalhes)
                    {
                        chave = new BusinessEntity.ChaveOrdem
                        {
                            DataOrdem = item.DataOrdem,
                            NumeroOrdem = item.NumeroOrdem,
                            NumeroOrdemSubSequencia = item.NumeroOrdemSubSequencia
                        };

                        this.DescasarOrdem(this.DetalheOrdemToOrdem(item), BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdemMataPreBoleto);
                        raManutencaoOrdens.CancelarOrdem(chave);
                    }
                }

                this.DescasarOrdem(ordem, BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdemMataPreBoleto);
                raManutencaoOrdens.CancelarOrdem(request);                                             

                //Justificativa está Pendente Mensageria
                if (justificativa.PendenteMensageria)
                {
                    justificativa.DataHoraOrdem = ordem.DataHoraOrdem.Value;
                    justificativa.CodigoCliente = ordem.CodigoCliente;
                    blJustificativa.IncluirJustificativaPendente(justificativa);
                }
                else
                {
                    justificativa.DataHoraOrdem = ordem.DataHoraOrdem.Value;
                    blJustificativa.IncluirJustificativa(justificativa);
                }

                this.CalcularFinanceiro();
            }
        }

        private BusinessEntity.Ordem DetalheOrdemToOrdem(BusinessEntity.DetalheOrdem detalhe)
        {
            if (detalhe == null) return null;

            return new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Ordem
            {
                Ativo = detalhe.Ativo,
                Carteira = detalhe.Carteira,
                DataOrdem = detalhe.DataOrdem,
                Mercado = detalhe.Mercado,
                NaturezaOperacao = detalhe.NaturezaOperacao,
                NumeroOrdem = detalhe.NumeroOrdem,
                NumeroOrdemSubSequencia = detalhe.NumeroOrdemSubSequencia,
                PrazoVencimentoTermo = detalhe.PrazoVencimentoTermo,
                Preco = detalhe.Preco,
                Quantidade = detalhe.Quantidade,
                QuantidadeExecutada = detalhe.QuantidadeExecutada
            };
        }

        /// <summary>
        /// Cancela Detalhe Ordem
        /// </summary>
        /// <param name="request"></param>
        public void CancelarDetalheOrdem(BusinessEntity.ChaveOrdem request)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = null;
            Movimento.BusinessEntity.InformacoesMovimento infoMovimento = null;
            BusinessEntity.Ordem ordem = null;
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();

            //Verificar se usuário possui permissão para cancelar ordens
            if (!AuthorizationContext.Current.CheckUserAccess("EORD", "ORD"))
                throw new BusinessException(USUARIO_SEM_PERMISSAO_PARA_CANCELAR_ORDENS);

            blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            infoMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());

            //Valida estado do movimento
            if (infoMovimento.EstadoMovimento != Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            //Verifica se subsequência da ordem é maior que zero
            if (request.NumeroOrdemSubSequencia > 0)
            {
                ordem = this.ObterOrdem(request);
            }
            else
            {
                throw new BusinessException(NUMERO_SUBSEQUENCIA_IGUAL_ZERO);
            }

            //Verifica se detalhe informado existe
            if (ordem == null)
                throw new BusinessException(DETALHE_ORDEM_NAO_EXISTE);

            //Validar se detalhe pode ser cancelado
            BusinessRulesValidation.ValidadorCancelamentoDetalheOrdem validacaoCancelamentoDetalheOrdem = new BusinessRulesValidation.ValidadorCancelamentoDetalheOrdem(infoMovimento);
            validacaoCancelamentoDetalheOrdem.EntityToValidate = ordem;

            BusinessRulesValidator validador = new BusinessRulesValidator();
            validador.AddValidation("ValidadorCancelamentoDetalheOrdem", validacaoCancelamentoDetalheOrdem);
            validador.Validate();

            //Verifica se retornou algum erro na validação
            if (!validador.HasErrors)
            {
                if (ordem.QuantidadeExecutada > 0)
                {
                    this.DescasarOrdem(ordem, Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdemMataPreBoleto);
                }

                raManutencaoOrdens.CancelarOrdem(request);

                this.CalcularFinanceiro();
            }
        }

        /// <summary>
        /// Descasa Ordem
        /// </summary>
        /// <param name="request"></param>
        /// <param name="tipoExecucao"></param>
        private void DescasarOrdem(BusinessEntity.Ordem request, BusinessEntity.Enum.TipoExecucaoDescasar tipoExecucao)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = null;
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = null;
            Movimento.BusinessEntity.InformacoesMovimento infoMovimento = null;
            BusinessEntity.Resultado resultado = null;
            BusinessEntity.ChaveOrdem chaveOrdem = null;

            //Verificar se ordem está casada ou parcialmente casada
            if (request.QuantidadeExecutada > 0)
            {
                blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
                raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();

                //Tradução para chave
                chaveOrdem = new BusinessEntity.ChaveOrdem
                {
                    DataOrdem = request.DataOrdem,
                    NumeroOrdem = request.NumeroOrdem,
                    NumeroOrdemSubSequencia = request.NumeroOrdemSubSequencia
                };

                //Obtem informações do movimento
                infoMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());

                //Descasa ordem
                resultado = raManutencaoOrdens.DescasarOrdem(chaveOrdem, infoMovimento.DataMovimento, BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdem);

                //Verificar se houve sucesso no processo de descasar?
                if (!resultado.Sucesso)
                {
                    if (resultado.CodigoErro == -1)
                        throw new BusinessException(ERRO_EM_DESCASAR);
                    else
                        this.TratarExcecoes(resultado);
                }
            }
        }

        /// <summary>
        /// Casa Detalhes Ordem
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Enum.SituacaoCasamento CasarDetalhesOrdem(BusinessEntity.ChaveOrdem request)
        {
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
            BusinessEntity.Resultado resultado = null;
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = null;
            Movimento.BusinessEntity.InformacoesMovimento infoMovimento = null;
            BusinessEntity.DadosCasamento dadosCasamento = null;

            blControleMovimentoOrdens = new Sinacor.Servico.Bovespa.Movimento.BusinessLogic.ControleMovimentoOrdens();
            infoMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());

            dadosCasamento = new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.DadosCasamento
            {
                DataPregao = infoMovimento.DataMovimento,
                Ordem = request
            };

            //Casar detalhes ordem
            resultado = raManutencaoOrdens.CasarDetalhesOrdem(dadosCasamento);

            //Verificar resultado
            if (!resultado.Sucesso)
            {
                if (resultado.CodigoErro == -1)
                    throw new BusinessException(ERRO_CASAR_DETALHES);
                else
                    this.TratarExcecoes(resultado);
            }

            return Sinacor.Infra.Service.Common.EnumConverter.Parse<BusinessEntity.Enum.SituacaoCasamento>(resultado.Valor.ToString());
        }

        /// <summary>
        /// Altera ordem
        /// </summary>
        /// <param name="request"></param>
        /// <param name="justificativa"></param>
        public void AlterarOrdem(BusinessEntity.Ordem request, BusinessEntity.Justificativa justificativa)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = null;
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
            BusinessLogic.Justificativa blJustificativa = new BusinessLogic.Justificativa();
            Movimento.BusinessEntity.InformacoesMovimento infoMovimento = null;
            BusinessRulesValidation.ValidadorAlteracaoOrdem validacaoAlteracaoOrdem = null;
            BusinessRulesValidator validador = null;
            
            //Validar permissão para alterar a ordem
            if (!AuthorizationContext.Current.CheckUserAccess("AORD", "ORD"))
                throw new BusinessException(ERRO_ACESSO_INCLUSAO_ORDEM);

            //Obter informações sobre o movimento
            blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            infoMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());

            //Valida estado do movimento
            if (infoMovimento.EstadoMovimento != Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
                throw new BusinessException(ERRO_MOVIMENTO_FECHADO);

            //Validar alterações na ordem
            validacaoAlteracaoOrdem = new BusinessRulesValidation.ValidadorAlteracaoOrdem();
            validacaoAlteracaoOrdem.EntityToValidate = request;
            validador = new BusinessRulesValidator();
            validador.AddValidation("ValidadorAlteracaoOrdem", validacaoAlteracaoOrdem);
            validador.Validate();

            //Detectar e processar ações na ordem a partir dos campos que foram alterados
            this.DetectarAcoesAlteracao(request, validacaoAlteracaoOrdem.OrdemOriginal);

            if (justificativa != null)
            {
                //Justificativa está Pendente Mensageria
                if (justificativa.PendenteMensageria)
                {
                    justificativa.DataHoraOrdem = request.DataHoraOrdem.Value;
                    justificativa.CodigoCliente = request.CodigoCliente;
                    blJustificativa.IncluirJustificativaPendente(justificativa);
                }
                else
                {
                    justificativa.DataHoraOrdem = request.DataHoraOrdem.Value;
                    blJustificativa.IncluirJustificativa(justificativa);
                }
            }
            else
                blJustificativa.IncluirJustificativa(justificativa);

            //Alterar ordem
            raManutencaoOrdens.AlterarOrdem(request);

            //Atualizar observações
            raManutencaoOrdens.AlterarObservacao(request);
        }


        /// <summary>
        /// Detectar ações alteração
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        private void DetectarAcoesAlteracao(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            bool resultado = false;

            resultado = this.ProcessarCaso1(ordemAtual, ordemOriginal);

            if (!resultado)
                resultado = this.ProcessarCaso1(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso2(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso3(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso4(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso5(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso6(ordemAtual, ordemOriginal);
            if (!resultado)
                resultado = this.ProcessarCaso7(ordemAtual, ordemOriginal);
        }

        /// <summary>
        /// Processar Caso 1
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso1(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            BusinessEntity.ChaveOrdem chave = null;

            //Verifica se quantidade da ordem foi reduzida
            if (ordemAtual.Quantidade >= ordemOriginal.Quantidade)
            {
                //Verifica se mercado foi alterado
                if (ordemAtual.Mercado == ordemOriginal.Mercado)
                {
                    //Verifica se ativo foi alterado
                    if (ordemAtual.Ativo == ordemOriginal.Ativo)
                    {
                        //Verifica se natureza da operação foi alterada
                        if (ordemAtual.NaturezaOperacao == ordemOriginal.NaturezaOperacao)
                        {
                            //Verifica se bolsa foi alterada
                            if (ordemAtual.CodigoBolsa == ordemOriginal.CodigoBolsa)
                            {
                                //Verifica se prazo do termo foi alterado
                                if (ordemAtual.PrazoVencimentoTermo == ordemOriginal.PrazoVencimentoTermo)
                                {
                                    //Verifica se preço da ordem foi alterado
                                    if (ordemAtual.Preco == ordemOriginal.Preco)
                                    {
                                        //Verifica se tipo da ordem foi alterado
                                        if (ordemAtual.TipoOrdem == ordemOriginal.TipoOrdem)
                                        {
                                            //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                                            return false;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //Verifica se ordem foi distribuída
            //Se não foi distribuida, executar bloco abaixo
            if (!ordemOriginal.Distribuida.HasValue ||
                !ordemOriginal.Distribuida.Value)
            {
                //Descasa ordem e cancelar pré-boletos
                this.DescasarOrdem(ordemOriginal, BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdemMataPreBoleto);

                chave = new BusinessEntity.ChaveOrdem
                {
                    DataOrdem = ordemOriginal.DataOrdem,
                    NumeroOrdem = ordemOriginal.NumeroOrdem,
                    NumeroOrdemSubSequencia = ordemOriginal.NumeroOrdemSubSequencia
                };

                //Gera log
                this.AtualizarIndicadorLog(chave);

                //Calcula financeiro
                this.CalcularFinanceiro();
            }

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 2
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso2(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            BusinessEntity.ChaveOrdem chave = null;
            
            //Verifica se cliente foi alterado
            if (ordemAtual.CodigoCliente == ordemOriginal.CodigoCliente)
            {
                //Verifica se tipo de liquidação foi alterado
                if (ordemAtual.TipoLiquidacao == ordemOriginal.TipoLiquidacao)
                {
                    //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                    return false;
                }
            }

            //Verifica se ordem foi distribuída
            //Se não foi distribuida, executar bloco abaixo
            if (ordemOriginal.Distribuida.HasValue &&
                !ordemOriginal.Distribuida.Value)
            {
                //Descasa ordem e cancelar pré-boletos
                this.DescasarOrdem(ordemOriginal, BusinessEntity.Enum.TipoExecucaoDescasar.DescasaOrdem);

                chave = new BusinessEntity.ChaveOrdem
                {
                    DataOrdem = ordemOriginal.DataOrdem,
                    NumeroOrdem = ordemOriginal.NumeroOrdem,
                    NumeroOrdemSubSequencia = ordemOriginal.NumeroOrdemSubSequencia
                };

                //Gera log
                this.AtualizarIndicadorLog(chave);

                //Calcula financeiro
                this.CalcularFinanceiro();
            }

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 3
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso3(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            BusinessEntity.ChaveOrdem chave = null;
            
            //Verifica se percentual de corretagem foi alterado
            if (ordemAtual.PercentualCorretagem == ordemOriginal.PercentualCorretagem)
            {
                //Verifica se carteira foi alterada
                if (ordemAtual.Carteira == ordemOriginal.Carteira)
                {
                    //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                    return false;
                }
            }

            //Verifica se ordem foi distribuída
            //Se não foi distribuida, executar bloco abaixo
            if (ordemOriginal.Distribuida.HasValue &&
                !ordemOriginal.Distribuida.Value)
            {
                chave = new BusinessEntity.ChaveOrdem
                {
                    DataOrdem = ordemOriginal.DataOrdem,
                    NumeroOrdem = ordemOriginal.NumeroOrdem,
                    NumeroOrdemSubSequencia = ordemOriginal.NumeroOrdemSubSequencia
                };
                
                //Gera log
                this.AtualizarIndicadorLog(chave);

                //Altera alocação
                this.AlterarAlocacao(ordemAtual);

                //Calcula financeiro
                this.CalcularFinanceiro();
            }

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 4
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso4(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            //Verifica se dólar foi alterado
            if (ordemAtual.ValorDolar == ordemOriginal.ValorDolar)
            {
                //Verifica se indicador de sistema externo foi alterado
                if (ordemAtual.IndicadorSistemaExterno == ordemOriginal.IndicadorSistemaExterno)
                {
                    //Verifica se indicador de liquidação externa foi alterado
                    if (ordemAtual.IndicadorSistemaExterno == ordemOriginal.IndicadorSistemaExterno)
                    {
                        //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                        return false;
                    }
                }
            }

            //Verifica se ordem foi distribuída
            //Se não foi distribuida, executar bloco abaixo
            if (ordemOriginal.Distribuida.HasValue &&
                !ordemOriginal.Distribuida.Value)
            {
                //Altera alocação
                this.AlterarAlocacao(ordemAtual);

                //Calcula financeiro
                this.CalcularFinanceiro();
            }

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 5
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso5(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            BusinessEntity.ChaveOrdem chave = null;
            
            //Verifica se atributo discricionário foi alterado
            if (ordemAtual.Discricionaria == ordemOriginal.Discricionaria)
            {
                //Verifica se quantidade anexo IV foi alterado
                if (ordemAtual.QuantidadeAnexoIV == ordemOriginal.QuantidadeAnexoIV)
                {
                    //Verifica se quantidade anexo V foi alterado
                    if (ordemAtual.QuantidadeAnexoV == ordemOriginal.QuantidadeAnexoV)
                    {
                        //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                        return false;
                    }
                }
            }

            //Verifica se ordem foi distribuída
            //Se não foi distribuida, executar bloco abaixo
            if (ordemOriginal.Distribuida.HasValue &&
                !ordemOriginal.Distribuida.Value)
            {
                chave = new BusinessEntity.ChaveOrdem
                {
                    DataOrdem = ordemOriginal.DataOrdem,
                    NumeroOrdem = ordemOriginal.NumeroOrdem,
                    NumeroOrdemSubSequencia = ordemOriginal.NumeroOrdemSubSequencia
                };

                //Gera log
                this.AtualizarIndicadorLog(chave);
            }

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 6
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso6(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            BusinessEntity.ChaveOrdem chave = null;
            
            //Verifica se quantidade da ordem foi acrescida
            if (ordemAtual.Quantidade <= ordemOriginal.Quantidade)
            {
                //Verifica se operador foi alterado
                if (ordemAtual.CodigoOperador == ordemOriginal.CodigoOperador)
                {
                    //Verifica se percentual de Financiamento foi alterado
                    if (ordemAtual.PercentualFinanciamento == ordemOriginal.PercentualFinanciamento)
                    {
                        //Verifica se valor de financiamento foi alterado
                        if (ordemAtual.ValorFinanciamento == ordemOriginal.ValorFinanciamento)
                        {
                            //Verifica se emissor foi alterado
                            if (ordemAtual.NomeEmissor == ordemOriginal.NomeEmissor)
                            {
                                if (ordemAtual.NomeEmissor == ordemOriginal.NomeEmissor)
                                {
                                    //Retorna "false" caso nenhuma dessas propriedadas tenha sofrido alteração
                                    return false;
                                }
                            }
                        }
                    }
                }
            }

            chave = new BusinessEntity.ChaveOrdem
            {
                DataOrdem = ordemOriginal.DataOrdem,
                NumeroOrdem = ordemOriginal.NumeroOrdem,
                NumeroOrdemSubSequencia = ordemOriginal.NumeroOrdemSubSequencia
            };

            //Gera log
            this.AtualizarIndicadorLog(chave);

            //Retorna "true" caso uma dessas propriedadas tenha sofrido alteração
            return true;
        }

        /// <summary>
        /// Processar Caso 7
        /// </summary>
        /// <param name="ordemAtual"></param>
        /// <param name="ordemOriginal"></param>
        /// <returns></returns>
        private bool ProcessarCaso7(BusinessEntity.Ordem ordemAtual, BusinessEntity.Ordem ordemOriginal)
        {
            if (ordemAtual.Situacao != ordemOriginal.Situacao)
            {
                //Alterar situação da ordem
                this.AlterarSituacaoOrdem(ordemAtual);

                //Calcular financeiro
                this.CalcularFinanceiro();

                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// Atualizar Indicador Log
        /// </summary>
        /// <param name="request"></param>
        private void AtualizarIndicadorLog(BusinessEntity.ChaveOrdem request)
        {
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();

            raManutencaoOrdens.AtualizarIndicadorLog(request);
        }

        /// <summary>
        /// Altera alocacao
        /// </summary>
        /// <param name="request"></param>
        private void AlterarAlocacao(BusinessEntity.Ordem request)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
            Movimento.BusinessEntity.InformacoesMovimento informacoesMovimento = null;
            BusinessEntity.Resultado resultado = null;


            informacoesMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());
            resultado = raManutencaoOrdens.AlterarAlocacao(request, informacoesMovimento.DataMovimento);

            if (!resultado.Sucesso)
            {
                if (resultado.CodigoErro == -1)
                    throw new BusinessException(ERRO_INESPERADO_ALTERACAO_ALOCACAO);
                else
                    this.TratarExcecoes(resultado);
            }
        }

        /// <summary>
        /// Alterar Situacao Ordem
        /// </summary>
        /// <param name="ordem"></param>
        private void AlterarSituacaoOrdem(BusinessEntity.Ordem ordem)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens blControleMovimentoOrdens = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            ResourceAccess.ManutencaoOrdens raManutencaoOrdens = new ResourceAccess.ManutencaoOrdens();
            Movimento.BusinessEntity.InformacoesMovimento informacoesMovimento = null;
            BusinessEntity.Resultado resultado = null;

            informacoesMovimento = blControleMovimentoOrdens.ObterInformacoesMovimento(new Sinacor.Servico.Bovespa.Movimento.BusinessEntity.DataMovimento());
            resultado = raManutencaoOrdens.AlterarSituacaoOrdem(ordem, informacoesMovimento.DataMovimento);

            if (!resultado.Sucesso)
            {
                if (resultado.CodigoErro == -1)
                    throw new BusinessException(ERRO_INESPERADO_ALTERACAO_SITUACAO_ORDEM);
                else
                    this.TratarExcecoes(resultado);
            }
        }

        public BusinessEntity.ValorOrdem CalcularValorOrdem(BusinessEntity.ChaveOrdem request)
        {
            BusinessEntity.Ordem ordem = null;
            Titulo.BusinessLogic.Titulo businessTitulo = null;
            Titulo.BusinessEntity.Titulo titulo = null;
            BusinessEntity.ValorOrdem retorno = null;
            BusinessLogic.Negocio businessNegocio = null;
            List<BusinessEntity.Negocio> negocios = null;

            if (request == null)
                throw new BusinessException(ERRO_PARAMETRONAOINFORMADO);

            ordem = ObterOrdem(request);

            if (ordem == null)
                throw new BusinessException(OBJETO_ORDEM_NULO);

            retorno = new BusinessEntity.ValorOrdem();
            retorno.ValorExecutado = 0;
            retorno.ValorNaoExecutado = 0;

            if (ordem.QuantidadeExecutada > 0)
            {
                businessNegocio = new BusinessLogic.Negocio();
                negocios = businessNegocio.ConsultarNegociosExecutados(request);

                if (negocios != null
                    && negocios.Count > 0)
                {
                    foreach (BusinessEntity.Negocio item in negocios)
                    {
                        retorno.ValorExecutado += (item.Quantidade * item.Preco) / item.FatorValorizacao;
                    }
                }
            }

            if (ordem.QuantidadeExecutada == 0
               || ordem.QuantidadeExecutada != ordem.Quantidade)
            {
                titulo = new Titulo.BusinessEntity.Titulo();
                titulo.Codigo = ordem.Ativo;
                titulo.DataOrdem = ordem.DataOrdem;

                if (ordem.Mercado.HasValue)
                {
                    switch (ordem.Mercado.Value)
                    {
                        case BusinessEntity.Enum.TipoMercado.Vista:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Vista;
                            break;
                        case BusinessEntity.Enum.TipoMercado.OpcaoCompra:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.OpcaoCompra;
                            break;
                        case BusinessEntity.Enum.TipoMercado.OpcaoVenda:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.OpcaoVenda;
                            break;
                        case BusinessEntity.Enum.TipoMercado.ExercicioOpcaoCompra:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.ExercicioOpcaoCompra;
                            break;
                        case BusinessEntity.Enum.TipoMercado.ExercicioOpcaoVenda:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.ExercicioOpcaoVenda;
                            break;
                        case BusinessEntity.Enum.TipoMercado.Fracionario:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Fracionario;
                            break;
                        case BusinessEntity.Enum.TipoMercado.Estruturado:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Estruturado;
                            break;
                        case BusinessEntity.Enum.TipoMercado.Leilao:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Leilao;
                            break;
                        case BusinessEntity.Enum.TipoMercado.Termo:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Termo;
                            break;
                        case BusinessEntity.Enum.TipoMercado.LeilaoNaoCotados:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.LeilaoNaoCotados;
                            break;
                        case BusinessEntity.Enum.TipoMercado.Futuro:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.Futuro;
                            break;
                        case BusinessEntity.Enum.TipoMercado.VencimentoFuturo:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.VencimentoFuturo;
                            break;
                        case BusinessEntity.Enum.TipoMercado.BOX:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.BOX;
                            break;
                        case BusinessEntity.Enum.TipoMercado.CotasETF:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.CotasETF;
                            break;
                        case BusinessEntity.Enum.TipoMercado.IntegralizacaoResgateCotas:
                            titulo.TipoMercado = Titulo.BusinessEntity.Enum.TipoMercado.IntegralizacaoResgateCotas;
                            break;
                    }
                }

                businessTitulo = new Titulo.BusinessLogic.Titulo();
                titulo = businessTitulo.ObterTitulo(titulo);

                retorno.ValorNaoExecutado = ((ordem.Quantidade - ordem.QuantidadeExecutada) * titulo.CotacaoMediaTitulo) / titulo.FatorCotacao;
                retorno.ValorTotal = retorno.ValorExecutado + retorno.ValorNaoExecutado;
            }
            else
            {
                retorno.ValorTotal = retorno.ValorExecutado;
            }

            return retorno;
        }
        #endregion

    }

}